package com.oracle.scjp.threads;

public class WaitDemo {
	public static void main(String[] args) {
		Target target = new Target();
		synchronized (target) {
			// start threads...
			for (int i = 0; i < 5; i++) {
				new Waiter("Waiter#"+i, target).start();
			}
			
			try {
				System.out.println("Threads will wait while main sleeps.");
				Thread.sleep(2000);
			} catch (InterruptedException e) { 
			} finally {
				System.out.println("Make Target Ready!");
				target.setReady(true);	
			}
		}
	}
}

class Waiter extends Thread {
	
	private Target target;
	
	public Waiter(String name, Target target) {
		super(name);
		this.target = target;
	}
	
	@Override
	public void run() {
		synchronized (target) {
			System.out.println(getName() + " holds the monitor of target.");
			while(!target.isReady()) {
				try {
					target.wait();
				} catch (InterruptedException e) {
					System.out.println(getName() + " is interrupted!");
				}
			}
//			target.setReady(false); // will make next thread wait forever
			System.out.println(getName() + " did anything on target obj.");
			target.notifyAll(); 
			System.out.println(getName() + " release target obj monitor.");
		}
	}
}

class Target {
	private boolean isReady = false;

	public boolean isReady() {
		return isReady;
	}

	public void setReady(boolean isReady) {
		this.isReady = isReady;
	}
}